﻿using System;
using System.Threading;
using Assets.Scripts.network.socket;
using UnityEngine;

public class HeartbeatManager
{
    private int maxHeartTimes = 100;//最大心跳次数，达到最大心跳次数之后，就会主动关闭连接
    private int responseTimeout = 30;
    private int heartTime = 5;//心跳时间，当客户端没有业务请求时，即每隔多长时间创建一次心跳，单位秒
    private int maxTryConnectTimes = 3;
    private long lastRequestTime;//最近一次消息的交互时间，单位秒
    private GatewayClient gatewayClient;
    private int heartTimes;
    private long lastResponseTime;//收到的最近一次服务器响应消息
    private volatile int nowTryConnectTimes;

    private Timer timer;
    private volatile bool IsStart;
    private bool enableHeartbeat;//是否开启心跳
    private GameSocketManager gameSocketManager;

    private volatile bool isConnecting;
    public HeartbeatManager(GatewayClient gatewayClient, GameSocketManager gameSocketManager, bool enableHeartbeat)
    {
        this.gameSocketManager = gameSocketManager;
        this.enableHeartbeat = enableHeartbeat;
        this.gatewayClient = gatewayClient;
        this.lastRequestTime = DateUtil.CurrentSecond();
        this.lastResponseTime = DateUtil.CurrentSecond();
    }

    public void Shutdown()
    {
        IsStart = false;
        gameSocketManager.CloseConnect();
        heartTimes = 0;
        lastRequestTime = 0;
        lastResponseTime = DateUtil.CurrentSecond();
        if (timer != null)
        {
            timer.Dispose();
        }
    }
    public void UpdateLastRequestTime()
    {
        this.lastRequestTime = DateUtil.CurrentSecond();
        heartTimes = 0;
    }

    public void UpdateLastResponseTime()
    {
        this.lastResponseTime = DateUtil.CurrentSecond();
    }
    public void Start()
    {
        if (enableHeartbeat)
        {
            if (timer == null)
            {
                timer = new Timer(FixUpdate, null, 1000, 1000);
            }
            this.UpdateLastRequestTime();
            this.UpdateLastResponseTime();
            IsStart = true;
        }

    }
    public void RestartConnectServer()
    {
        IsStart = false;
        if (!isConnecting)
        {
            isConnecting = true;
            nowTryConnectTimes++;
        }
        else
        {
            Thread.Sleep(3);
        }
        Debug.Log("重新连接,第" + nowTryConnectTimes + "次尝试");
        if (nowTryConnectTimes >= maxTryConnectTimes)
        {
            Debug.Log("重连已达最大尝试次数，不再连接");
            this.Shutdown();
            return;
        }

        gatewayClient.Connect((state) =>
        {
            isConnecting = false;
            if (state == SocketStateEnum.ConnectSuccess)
            {
                nowTryConnectTimes = 0;
            }
            else
            {
                Debug.Log("连接失败，请检测网络");
            }
        });

    }


    private void FixUpdate(object satte)
    {
   
        try
        {
            if (!IsStart)
            {
                return;
            }
            if (!gatewayClient.IsConnected())
            {
                if (IsStart)
                {
                    this.RestartConnectServer();
                }
            }
            else
            {
                CheckAndSendHeartMessage();
            }
        }
        catch (Exception e)
        {
            Debug.Log("心跳异常" + e);
        }
    }
    private void CheckAndSendHeartMessage()
    {
        if (heartTimes > maxHeartTimes)
        {
            Debug.Log("达到最大心跳次数，判断客户端可能已不玩游戏了，主动断开连接");
            IsStart = false;
            return;
        }

        long nowTime = DateUtil.CurrentSecond();
        if (gatewayClient.IsConnected() && (nowTime - lastResponseTime > responseTimeout))
        {

            IsStart = false;
            this.RestartConnectServer();

        }
        else if (gatewayClient.IsConnected() && (nowTime - lastRequestTime > heartTime))
        {
            //send heart message
            HeartbeatMessageRequest request = new HeartbeatMessageRequest();
            gatewayClient.Send<HeartbeatMessageResponse>(request, (data) =>
            {
                Debug.Log("收到服务端心跳信息");
            });
            this.lastRequestTime = nowTime;
            heartTimes++;
        }
    }

}
